﻿using Asion.Dapper.SqlBuilder;
using Asion.Dapper.SqlBuilder.Condition;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using static Asion.Dapper.SqlMapperExtensions;

namespace Asion.Dapper
{
    public interface ISelectColumn<TEntity> : ICondition where TEntity : IEntity
    {

    }

    public class SelectColumn<TEntity> : BaseCondition<TEntity>, ISelectColumn<TEntity>, IGetSql where TEntity : IEntity
    {
        private IList<string> columns;

        public SelectColumn(string[] columns)
        {
            this.columns = columns;
        }


        /// <summary>
        /// build select cloumn by list
        /// </summary>
        /// <param name="cloumns"></param>
        /// <returns></returns>
        private string BuildSql()
        {


            var stringBuilder = new StringBuilder();
            var addedAny = false;
            for (var i = 0; i < columns.Count(); i++)
            {
                var column = columns[i];
                var property = _custom_table_mappinghandle.GetColumnMapping(column);
                if (property == null)
                {
                    throw new ArgumentException($"column that {column}  does not exist ");
                }
                if (addedAny)
                    stringBuilder.Append(",");
                stringBuilder.Append(_encap_sulation.EncapSulation(property.DataColumnName) + $" as {property.ColumnName}");
                addedAny = true;
            }
            var sql = stringBuilder.ToString();

            return sql;
        }

        public string GetSql()
        {
            return BuildSql();
        }
    }


    public static class SimpleSelectColumnExtend
    {
        public static SelectColumn<TEntity> ToSimpleSelectColum<TEntity>(this string[] condtion) where TEntity : IEntity
        {
            return new SelectColumn<TEntity>(condtion);
        }
    }

    public class AllSelectColumn<TEntity> : BaseCondition<TEntity>, ISelectColumn<TEntity>, IGetSql where TEntity : IEntity
    {


        private static ConcurrentDictionary<PropertyIdentity, string> all_sql = new ConcurrentDictionary<PropertyIdentity, string>();

        public AllSelectColumn()
        {

        }

        public string GetSql()
        {
            return BuildSql();
        }

        /// <summary>
        /// build select cloumn by list
        /// </summary>
        /// <param name="cloumns"></param>
        /// <returns></returns>
        private string BuildSql()
        {
            var identity = _custom_table_mappinghandle.GetIdentity();
            if (all_sql.ContainsKey(identity))
            {
                all_sql.TryGetValue(identity, out string result);
                return result;
            }
            var columns = _custom_table_mappinghandle.GetSelectColumn();
            var stringBuilder = new StringBuilder();
            var addedAny = false;
            for (var i = 0; i < columns.Count(); i++)
            {
                var property = columns.ElementAt(i);

                if (addedAny)
                    stringBuilder.Append(",");
                stringBuilder.Append(_encap_sulation.EncapSulation(property.DataColumnName) + $" as {property.ColumnName}");
                addedAny = true;
            }
            var sql = stringBuilder.ToString();
            all_sql.TryAdd(identity, sql);
            return sql;
        }

    }

    public class SelectColumnFactory<TEntity> : BaseCondition<TEntity> where TEntity : IEntity
    {
        public SelectColumnFactory(ISelectColumn<TEntity> condtion)
        {
            where = condtion;

        }

        private ISelectColumn<TEntity> where;


        public string GetSql()
        {
            if (where is SelectColumn<TEntity>)
            {
                var condtion = where as SelectColumn<TEntity>;

                return condtion.GetSql();
            }
            if (where is AllSelectColumn<TEntity>)
            {
                var condtion = where as AllSelectColumn<TEntity>;
                return condtion.GetSql();
            }
            throw new NotImplementedException("column condition");
        }


    }


    public static class SelectColumnFactoryExtend
    {
        public static SelectColumnFactory<TEntity> Build<TEntity>(this ISelectColumn<TEntity> condtion) where TEntity : IEntity
        {
            return new SelectColumnFactory<TEntity>(condtion);
        }
    }
}
